home *** CD-ROM | disk | FTP | other *** search
- /* $Header: tyrathect:Development:Perl::RCS:missing.c,v 1.2 1994/05/04 02:12:43 neeri Exp $
- *
- * Copyright (c) 1991-1994 Matthias Neeracher
- *
- * You may distribute under the terms of the Perl Artistic License,
- * as specified in the README file.
- *
- * $Log: missing.c,v $
- * Revision 1.2 1994/05/04 02:12:43 neeri
- * Added gmtime(), enabled utime(), reduced spinning.
- *
- * Revision 1.1 1994/03/01 23:38:17 neeri
- * Initial revision
- *
- */
-
- /* NEVER try including perl.h here ! */
-
- /* DISPATCH_START */
- #define MAC_CONTEXT
- #define MP_EXT
- #define MP_INIT(x) = x
-
- #include <time.h>
- #include <stdio.h>
- #include <AppleEvents.h>
- #include <Folders.h>
- #include <Events.h>
- #include <OSUtils.h>
- #include <LowMem.h>
- #include <GUSI.h>
- #include <TFileSpec.h>
- #include <TFileGlob.h>
- #include <fp.h>
- #include <LowMem.h>
-
- #define MEM_SIZE Size_t
-
- #include "config.h"
- #include "handy.h"
- #include "macish.h"
- #include "SubLaunch.h"
- #include "embed.h"
- /* DISPATCH_END */
-
- /* Calls that don't exist on the mac */
-
- /* Borrowed from msdos.c
- * Just pretend that everyone is a superuser
- */
- /* DISPATCH_START */
- #define ROOT_UID 0
- #define ROOT_GID 0
- int
- (getuid)(void)
- {
- return ROOT_UID;
- }
-
- int
- (geteuid)(void)
- {
- return ROOT_UID;
- }
-
- int
- (getgid)(void)
- {
- return ROOT_GID;
- }
-
- int
- (getegid)(void)
- {
- return ROOT_GID;
- }
-
- int
- (setuid)(int uid)
- {
- return (uid==ROOT_UID?0:-1);
- }
-
- int
- setgid(int gid)
- {
- return (gid==ROOT_GID?0:-1);
- }
-
- #undef execv
-
- (execv)()
- {
- croak("execv() not implemented on the Macintosh");
- }
-
- #undef execvp
-
- (execvp)()
- {
- croak("execvp() not implemented on the Macintosh");
- }
-
- kill()
- {
- croak("kill() not implemented on the Macintosh");
- }
- /* DISPATCH_END */
-
- char **environ;
- static char * gEnvpool;
- extern int StandAlone;
-
- char ** init_env(char ** env)
- {
- int envcnt = 0;
- int envsize = 0;
- int varlen;
- char * envpool;
- FILE * envfile = 0;
-
- for (envcnt = 0; env[envcnt]; envcnt++) {
- varlen = strlen(env[envcnt]);
- envsize += varlen+strlen(env[envcnt]+varlen+1)+2;
- }
-
- if (gEnvpool) {
- Safefree(environ);
- Safefree(gEnvpool);
- }
-
- New(50, environ, envcnt+1, char *);
- New(50, gEnvpool, envsize, char);
-
- envpool = gEnvpool;
- for (envcnt = 0; env[envcnt]; envcnt++) {
- environ[envcnt] = envpool;
- varlen = strlen(env[envcnt]);
- strcpy(envpool, env[envcnt]);
- envpool += varlen+1;
- envpool[-1] = '=';
- strcpy(envpool, env[envcnt]+varlen+1);
- envpool += strlen(env[envcnt]+varlen+1)+1;
- }
-
- environ[envcnt] = 0;
-
- return environ;
- }
-
- void install_env(Handle env)
- {
- int envcnt = 0;
- int envsize = 0;
- int varlen;
- char * envpool;
- char * max;
- char state;
- FILE * envfile = 0;
-
- if (gEnvpool) {
- Safefree(environ);
- Safefree(gEnvpool);
- }
-
- New(50, gEnvpool, GetHandleSize(env), char);
-
- state = HGetState(env);
- HLock(env);
- BlockMove(*env, (Ptr)gEnvpool, GetHandleSize(env));
- HSetState(env, state);
-
- envpool = gEnvpool;
- max = envpool + GetHandleSize(env);
- while (envpool < max) {
- ++envcnt;
- envpool += strlen(envpool)+1;
- }
-
- New(50, environ, envcnt+1, char *);
-
- envpool = gEnvpool;
- envcnt = 0;
- while (envpool < max) {
- environ[envcnt++] = envpool;
- envpool += strlen(envpool)+1;
- }
-
- environ[envcnt] = 0;
- }
-
- Handle retrieve_env()
- {
- char ** envp = environ;
- Handle env = NewHandle(0);
-
- while (*envp) {
- PtrAndHand(*envp, env, strlen(*envp)+1);
- ++envp;
- }
-
- return env;
- }
-
- typedef struct PD {
- struct PD * next;
- FILE * tempFile;
- FSSpec pipeFile;
- char * execute;
- long status;
- } PipeDescr, *PipeDescrPtr;
-
- static PipeDescrPtr pipes = nil;
- static Boolean sweeper = false;
-
- void sweep()
- {
- while (pipes)
- my_pclose(pipes->tempFile);
- sweeper = false;
- }
-
- typedef struct WEPDesc {
- struct WEPDesc * next;
- const char * command;
- EmulationProc proc;
- } WEPDesc, * WEPDescPtr;
-
- static WEPDescPtr gEmulators[128];
- static Boolean gHasEmulators = false;
-
- void AddWriteEmulationProc(const char * command, EmulationProc proc)
- {
- WEPDescPtr wepdesc = (WEPDescPtr) malloc(sizeof(WEPDesc));
-
- wepdesc->next = gEmulators[*command];
- wepdesc->command = command;
- wepdesc->proc = proc;
- gEmulators[*command] = wepdesc;
- }
-
- EmulationProc FindWriteEmulationProc(char * command, char ** rest)
- {
- char * end;
- WEPDescPtr queue;
-
- for (end = command; isalnum(*end); ++end);
-
- if (end == command || (*command & 0x80))
- return nil;
-
- for (queue = gEmulators[*command]; queue; queue = queue->next)
- if (!strncmp(command, queue->command, end-command))
- if (!queue->command[end-command]) {
- while (isspace(*end))
- ++end;
- *rest = end;
-
- return queue->proc;
- }
-
- return nil;
- }
-
- static int EmulatePwd(FILE * tempFile, char * command)
- {
- char curdir[256];
-
- if (!getcwd(curdir, 256))
- return -1;
-
- fprintf(tempFile, "%s\n", curdir);
-
- return 0;
- }
-
- static int EmulateHostname(FILE * tempFile, char * command)
- {
- char curhostname[256];
-
- if (gethostname(curhostname, 256))
- return -1;
-
- fprintf(tempFile, "%s\n", curhostname);
-
- return 0;
- }
-
- static int EmulateGlob(FILE * tempFile, char * command)
- {
- char curbuf[256];
- char * curcmd;
- Boolean relativePath;
- int colonCount;
- FileGlobRef glob;
- FSSpec spec;
- FSSpec curDir;
-
- for (curcmd = curbuf; !isspace(*command); )
- if (!(*curcmd++ = *command++))
- break;
-
- if (!(glob = NewFileGlob(curbuf)))
- return -1;
-
- relativePath = true;
-
- if (curbuf[0] == ':') {
- /* Explicitely relative path, e.g. <:*.c> */
- char ch;
-
- for (curcmd = curbuf+1; *curcmd == ':'; ++curcmd)
- ;
-
- ch = *curcmd;
- *curcmd = 0;
- Path2FSSpec(curbuf, &curDir);
- *curcmd = ch;
- colonCount = curcmd - curbuf;
- } else if (!strchr(curbuf, ':')) {
- /* Implicitely relative path, e.g. <*.c> */
- colonCount = 0;
- Path2FSSpec(":", &curDir);
- } else
- relativePath = false;
-
- while (FileGlob2FSSpec(glob, &spec)) {
- if (relativePath) {
- curcmd = FSp2DirRelPath(&spec, &curDir);
- if (colonCount) {
- int i = colonCount - (*curcmd == ':');
- while (i--)
- putc(':', tempFile);
- }
- } else
- curcmd = FSp2FullPath(&spec);
-
- fprintf(tempFile, "%s\n", curcmd);
- NextFileGlob(glob);
- }
- DisposeFileGlob(glob);
-
- return 0;
- }
-
- FILE * my_popen(char * command, char * mode)
- {
- PipeDescrPtr pipe;
-
- if (!gHasEmulators) {
- gHasEmulators = true;
- AddWriteEmulationProc("pwd", EmulatePwd);
- AddWriteEmulationProc("directory", EmulatePwd);
- AddWriteEmulationProc("Directory", EmulatePwd);
- AddWriteEmulationProc("hostname", EmulateHostname);
- AddWriteEmulationProc("glob", EmulateGlob);
- }
-
- if (!strcmp(command, "-"))
- croak("Implicit fork() on a Mac? No forking chance");
-
- New(666, pipe, 1, PipeDescr);
-
- if (!pipe)
- return NULL;
-
- if (FSpMakeTempFile(&pipe->pipeFile))
- goto failed;
- pipe->execute = nil;
-
- switch(*mode) {
- case 'r':
- {
- /* Ugh ! A hardcoded command ! */
- EmulationProc proc = FindWriteEmulationProc(command, &command);
-
- if (proc) {
- if (!(pipe->tempFile = fopen(FSp2FullPath(&pipe->pipeFile), "w")))
- goto delete;
- if (proc(pipe->tempFile, command))
- goto delete;
- fclose(pipe->tempFile);
- } else if (SubLaunch(command, nil, &pipe->pipeFile, &pipe->pipeFile, &pipe->status))
- goto delete;
-
- if (!(pipe->tempFile = fopen(FSp2FullPath(&pipe->pipeFile), "r")))
- goto delete;
- break;
- }
- case 'w':
- New(667, pipe->execute, strlen(command)+1, char);
- if (!pipe->execute || !(pipe->tempFile = fopen(FSp2FullPath(&pipe->pipeFile), "w")))
- goto delete;
- strcpy(pipe->execute, command);
- break;
- }
-
- pipe->next = pipes;
- pipes = pipe;
-
- if (!sweeper) {
- atexit(sweep);
- sweeper = true;
- }
-
- return pipe->tempFile;
- delete:
- if (pipe->execute)
- Safefree(pipe->execute);
- HDelete(pipe->pipeFile.vRefNum, pipe->pipeFile.parID, pipe->pipeFile.name);
- failed:
- Safefree(pipe);
-
- return NULL;
- }
-
- int my_pclose(FILE * f)
- {
- OSErr err;
- PipeDescrPtr * prev;
- PipeDescrPtr pipe;
-
- for (prev = (PipeDescrPtr *) &pipes; pipe = *prev; prev = &pipe->next)
- if (pipe->tempFile == f)
- break;
-
- if (!pipe)
- return -1;
-
- *prev = pipe->next;
-
- fclose(f);
-
- if (pipe->execute)
- err = SubLaunch(pipe->execute, &pipe->pipeFile, nil, nil, &pipe->status);
- else
- err = noErr;
-
- HDelete(pipe->pipeFile.vRefNum, pipe->pipeFile.parID, pipe->pipeFile.name);
- if (pipe->execute)
- Safefree(pipe->execute);
- Safefree(pipe);
-
- return err? -1 : (int) pipe->status;
- }
-
- #undef TUNESPIN
-
- void SpinMacCursor()
- {
- static long lastSpin = 0;
- static long lastAevt = 0;
- #ifdef TUNESPIN
- static long numSpins = 0;
- #endif
- long curSpin = LMGetTicks();
-
- #ifdef TUNESPIN
- ++numSpins;
- #endif
- if (curSpin - lastSpin < 5)
- return;
-
- #ifdef TUNESPIN
- printf("%d %d, ", curSpin, numSpins);
- #endif
- lastSpin = curSpin;
-
- sleep(0);
-
- if (!StandAlone && curSpin - lastAevt > 30) {
- /* Newer versions of the MPW Shell disable automatic processing of
- AppleEvents, but we want them!
- */
- EventRecord ev;
-
- lastAevt = curSpin;
- if (WaitNextEvent(highLevelEventMask, &ev, 0, nil)) {
- AEProcessAppleEvent(&ev); /* Ignore errors */
- lastAevt -= 25; /* Retry sooner if successful */
- }
- }
- }
-
- /* DISPATCH_START */
- struct tm *localtime(const time_t *tp)
- {
- DateTimeRec dtr;
- MachineLocation loc;
- static struct tm statictime;
- static const short monthday[12] =
- {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
-
- Secs2Date(*tp, &dtr);
- statictime.tm_sec = dtr.second;
- statictime.tm_min = dtr.minute;
- statictime.tm_hour = dtr.hour;
- statictime.tm_mday = dtr.day;
- statictime.tm_mon = dtr.month - 1;
- statictime.tm_year = dtr.year - 1900;
- statictime.tm_wday = dtr.dayOfWeek - 1;
- statictime.tm_yday = monthday[statictime.tm_mon]
- + statictime.tm_mday - 1;
- if (1 < statictime.tm_mon && !(statictime.tm_year & 3))
- ++statictime.tm_yday;
- ReadLocation(&loc);
- if (!loc.latitude && !loc.longitude)
- statictime.tm_isdst = -1;
- else
- statictime.tm_isdst = (loc.u.dlsDelta & 0x80) != 0;
- return(&statictime);
- }
-
- struct tm * gmtime(const time_t * timer)
- {
- MachineLocation loc;
- long delta;
- time_t rolex;
-
- ReadLocation(&loc);
-
- if (!loc.latitude && !loc.longitude)
- return localtime(timer); /* This is incorrect unless you live in Greenwich */
-
- delta = loc.u.gmtDelta & 0xFFFFFF;
-
- if (delta & 0x800000)
- delta = (long) ((unsigned long) delta | 0xFF000000);
-
- rolex = (unsigned long) ((long) *timer - delta);
-
- return localtime(&rolex);
- }
- /* DISPATCH_END */
-
- clock_t mac_times(struct tms * t)
- {
- t->tms_utime = clock() - gStartClock;
- t->tms_stime = 0;
- t->tms_cutime = 0;
- t->tms_cstime = 0;
-
- return t->tms_utime;
- }
-
- #undef atof
-
- double mac_atof(const char * nptr)
- {
- /* The Mac returns NaN(17) on undefined strings, which is not acceptable
- for Perl
- */
- double res = atof(nptr);
-
- if (isnan(res) /* This doesn't work: && res == nan("17") */)
- return 0.0;
- else
- return res;
- }
-
- void CopyC2PStr(char * cstr, StringPtr pstr)
- {
- int len;
-
- for (len = 0; *cstr && len<256; )
- pstr[++len] = *cstr++;
-
- pstr[0] = len;
- }
-
-
- char * MPWFileName(char * file)
- {
- if (!strcmp(file, "Dev:Pseudo"))
- return gPseudoFileName;
- else if (!strncmp(file, "Dev:Pseudo:", 11))
- return file + 11;
- else
- return file;
- }
-
- static Boolean sPosCommit = true;
-
- char * MPWPosIndication(char * buf, char * file, long line)
- {
- file = MPWFileName(file);
-
- if (!sPosCommit)
- gFirstErrorLine = -1;
-
- if (gFirstErrorLine == -1 && !Path2FSSpec(file, &gFirstErrorFile)) {
- gFirstErrorLine = line;
- sPosCommit = false;
- }
-
- strcpy(buf, "File '");
- buf += 6;
-
- while (*file)
- if (*file == '\'') {
- strcpy(buf, "'∂''");
- buf += 3;
- ++file;
- } else
- *buf++ = *file++;
-
- if (buf[-1] == '\'' && buf[-2] == '\'')
- --buf;
- else
- *buf++ = '\'';
-
- return buf + sprintf(buf, "; Line %ld", line);
- }
-
- void MPWPosCommit()
- {
- sPosCommit = true;
- }
-
- int OverrideExtract(char * origname)
- {
- char file[256];
-
- strcpy(file+1, MPWFileName(origname));
- file[0] = strlen(file+1);
- ParamText((StringPtr) file, "\p", "\p", "\p");
-
- return Alert(270, (ModalFilterUPP) nil) == 1;
- }
-
- #define STACK_INTERVENTION_LIMIT 8192
-
- void StackAttack()
- {
- if (StackSpace() < STACK_INTERVENTION_LIMIT)
- croak("Stack space getting low ! Aborting script for your own good...\n");
- }
-
- void mac_initminiperl()
- {
- if (!gAppDir) {
- InitGraf((Ptr) &qd.thePort);
- signal(SIGINT, SIG_DFL);
- }
-
- gStartClock = LMGetTicks();
- }
-
- /* DISPATCH_START */
- pid_t (getpid)()
- {
- return 1;
- }
- /* DISPATCH_END */
-
- void SIOUXHandleOneEvent()
- {
- Debugger();
- }
-
- void InstallConsole()
- {
- Debugger();
- }
-
- void WriteCharsToConsole()
- {
- Debugger();
- }
-
- void ReadCharsFromConsole()
- {
- Debugger();
- }
-